template<class T>
void ResizableArray<T>::valid() const{
    ASSERT(this != 0, "internal error");
    ASSERT(this->size() >= 0, "internal error");
    ASSERT(this->size() == 0 || this->buf != 0, "internal error");
//    ASSERT(this->size() >  0 || this->buf == 0, "internal error");
    ASSERT(this->capacity() >= 0, "internal error");
    ASSERT(this->capacity() >= this->size(), "internal error");
}

template<class T>
void ResizableArray<T>::init(const int sz){
    this->sz = 0;
    this->buf = 0;
    ASSERT(sz >= 0, "size is incorrect");

    this->resize(sz);
    this->valid();
}


template<class T>
ResizableArray<T>::ResizableArray(const int sz, const T src[])
:   Array<T>(){
    this->init(sz);
    if (src != 0){
        this->move(0, src, sz);
    }
}

template<class T>
ResizableArray<T>::ResizableArray(const Array<T>& src)
:   Array<T>(){
    const int sz = src.size();
    this->init(sz);
    this->move(0, src, 0, sz);
}

template<class T> 
ResizableArray<T>::~ResizableArray(){
    this->valid();
    
    if (this->size() > 0){
        delete this->buf;
        this->buf = 0;
    }
    this->sz = -1;
}

template<class T> 
void ResizableArray<T>::reserve(int reqCapacity){
    ASSERT(reqCapacity >= 0, "invalid capacity");

    int bufCapacity = 0;
    if (buf != 0){
        bufCapacity = buf->size();
    }
    if (reqCapacity > bufCapacity){
        reqCapacity = (reqCapacity * 11 + 9) / 10;
        DynamicArray<T>* newBuf = new DynamicArray<T>(reqCapacity);
        ASSERT(newBuf != 0, "no memory");
        if (this->buf != 0){
            newBuf->move(0, *this->buf, 0, this->size());
            delete this->buf;
        }
        this->buf = newBuf;
    }

    ASSERT(reqCapacity <= this->capacity(), "internal error");
    this->valid();
}


template<class T> 
void ResizableArray<T>::resize(const int reqSize){
    ASSERT(reqSize >= 0, "invalid size");

    this->reserve(reqSize);
    this->sz = reqSize;
}

template<class T> 
void ResizableArray<T>::operator=(const Array<T>& src){
    this->assign(src);
}

template<class T> 
void ResizableArray<T>::append(const Array<T>& data){
    int dataSize = data.size();

    if (dataSize > 0){
        this->append(&data[0], dataSize);
    }
}

template<class T> 
void ResizableArray<T>::append(const T data[], const int dataSize){
    this->insert(this->size(), data, dataSize);
}

template<class T> 
void ResizableArray<T>::insert(const int start, const Array<T>& data){
    int dataSize = data.size();

    if (dataSize > 0){
        this->insert(start, &data[0], dataSize);
    }
}

template<class T> 
void ResizableArray<T>::insert(const int start, const T data[], const int dataSize){
    ASSERT(dataSize >= 0, "data size is invalid");
    ASSERT(dataSize == 0 || data != 0, "data size is invalid");

    if (start != this->size()){
        Array<T>::valid(start, start);
    }

    DynamicArray<T> dataCopy(dataSize, data);
    int reqSize = this->size() + dataSize;
    this->reserve(reqSize);

    buf->move(start + dataSize, *buf, start, this->size() - start);
    buf->move(start, dataCopy, 0, dataSize);

    this->resize(reqSize);
}

template<class T> 
void ResizableArray<T>::remove(const int start, const int sizeToRemove){
    ASSERT(start >= 0, "index is invalid");
    ASSERT(sizeToRemove >= 0, "size to remove is invalid");

    Array<T>::valid(start, sizeToRemove);
    this->buf->move(start, *this->buf, start + sizeToRemove, this->size() - start - sizeToRemove);
    this->resize(this->size() - sizeToRemove);
}

